using System;
using System.Collections.Generic;
using System.Diagnostics;
using UnityEngine;
using Utility.GameEvents.Core;

namespace Utility.GameEvents.Scriptable
{
    public abstract class GameEvent<T> : GameEventBase
    {
        [NonSerialized] private readonly List<IGameEventListener<T>> _listeners = new();
        [NonSerialized] private readonly List<Action<T>> _actionListeners = new();

        // 性能统计
        [NonSerialized] public int raiseCount;
        [NonSerialized] public double totalRaiseTimeMs;
        [NonSerialized] public T lastRaisedValue;

        public void Raise(T value)
        {
            var sw = Stopwatch.StartNew();

            lastRaisedValue = value;
            raiseCount++;
            foreach (var l in _listeners)
                l.OnEventRaised(value);
            
            foreach (var a in _actionListeners)
                a.Invoke(value);

            sw.Stop();
            totalRaiseTimeMs += sw.Elapsed.TotalMilliseconds;

            EventBus.Raise(new ScriptableEventWrapper<T>(this, value));
        }

        public override void RaiseRaw()
        {
            UnityEngine.Debug.LogWarning($"[GameEvent<{typeof(T).Name}>] 不支持无参 Raise");
        }
        
        public void Register(Action<T> action)
        {
            if (!_actionListeners.Contains(action))
                _actionListeners.Add(action);
        }
        
        

        public void Unregister(Action<T> action)
        {
            _actionListeners.Remove(action);
        }

        public void Register(IGameEventListener<T> listener)
        {
            if (!_listeners.Contains(listener))
                _listeners.Add(listener);
        }

        public void Unregister(IGameEventListener<T> listener)
        {
            _listeners.Remove(listener);
        }

        // 供调试器窗口访问
        public IReadOnlyList<IGameEventListener<T>> Listeners => _listeners.AsReadOnly();
    }

    [Serializable]
    public class DebugEventEntry<T>
    {
        public string targetName;
        public string methodSignature;
        public string parameter;
        public DateTime timestamp;

        public DebugEventEntry(IGameEventListener<T> listener, T value)
        {
            var comp = listener as MonoBehaviour;
            targetName = comp ? comp.name : "Unknown";
            methodSignature = listener.GetType().Name + ".OnEventRaised(" + typeof(T).Name + ")";
            parameter = value?.ToString();
            timestamp = DateTime.Now;
        }
    }
}